home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0192.ARJ / SCAN.ASM < prev    next >
Assembly Source File  |  1990-12-05  |  6KB  |  169 lines

  1. ; Scan converts an edge from (X1,Y1) to (X2,Y2), not including the
  2. ; point at (X2,Y2). If SkipFirst == 1, the point at (X1,Y1) isn't
  3. ; drawn; if SkipFirst == 0, it is. For each scan line, the pixel
  4. ; closest to the scanned edge without being to the left of the scanned
  5. ; edge is chosen. Uses an all-integer approach for speed & precision.
  6. ;
  7. ; C near-callable as:
  8. ;    void ScanEdge(int X1, int Y1, int X2, int Y2, int SetXStart,
  9. ;      int SkipFirst, struct HLine **EdgePointPtr);
  10. ;
  11. ; Edges must not go bottom to top; that is, Y1 must be <= Y2.
  12. ; Updates the pointer pointed to by EdgePointPtr to point to the next
  13. ;  free entry in the array of HLine structures.
  14.  
  15. HLine    struc
  16. XStart    dw    ?    ;X coordinate of leftmost pixel in scan line
  17. XEnd    dw    ?    ;X coordinate of rightmost pixel in scan line
  18. HLine    ends
  19.  
  20. Parms    struc
  21.         dw    2 dup(?) ;return address & pushed BP
  22. X1        dw    ?    ;X start coord of edge
  23. Y1        dw    ?    ;Y start coord of edge
  24. X2        dw    ?    ;X end coord of edge
  25. Y2        dw    ?    ;Y end coord of edge
  26. SetXStart    dw    ?    ;1 to set the XStart field of each
  27.                 ; HLine struc, 0 to set XEnd
  28. SkipFirst    dw    ?    ;1 to skip scanning the first point
  29.                 ; of the edge, 0 to scan first point
  30. EdgePointPtr    dw    ?    ;pointer to a pointer to the array of
  31.                 ; HLine structures in which to store
  32.                 ; the scanned X coordinates
  33. Parms    ends
  34.  
  35. ;Offsets from BP in stack frame of local variables.
  36. AdvanceAmt      equ     -2
  37. Height          equ     -4
  38. LOCAL_SIZE      equ     4    ;total size of local variables
  39.  
  40.     .model small
  41.     .code
  42.     public _ScanEdge
  43.     align    2
  44. _ScanEdge    proc
  45.     push    bp        ;preserve caller's stack frame
  46.     mov    bp,sp        ;point to our stack frame
  47.         sub     sp,LOCAL_SIZE   ;allocate space for local variables
  48.     push    si        ;preserve caller's register variables
  49.     push    di
  50.     mov    di,[bp+EdgePointPtr]
  51.     mov    di,[di]        ;point to the HLine array
  52.     cmp    [bp+SetXStart],1 ;set the XStart field of each HLine
  53.                 ; struc?
  54.     jz    HLinePtrSet    ;yes, DI points to the first XStart
  55.     add    di,XEnd        ;no, point to the XEnd field of the
  56.                 ; first HLine struc
  57. HLinePtrSet:
  58.     mov    bx,[bp+Y2]
  59.     sub    bx,[bp+Y1]    ;edge height
  60.     jle    ToScanEdgeExit    ;guard against 0-length & horz edges
  61.     mov    [bp+Height],bx    ;Height = Y2 - Y1
  62.     sub    cx,cx        ;assume ErrorTerm starts at 0 (true if
  63.                                 ; we're moving right as we draw)
  64.     mov    dx,1        ;assume AdvanceAmt = 1 (move right)
  65.     mov    ax,[bp+X2]
  66.     sub    ax,[bp+X1]      ;DeltaX = X2 - X1
  67.         jz      IsVertical         ;it's a vertical edge--special case it
  68.     jns    SetAdvanceAmt    ;DeltaX >= 0
  69.     mov    cx,1        ;DeltaX < 0 (move left as we draw)
  70.     sub    cx,bx        ;ErrorTerm = -Height + 1
  71.     neg    dx        ;AdvanceAmt = -1 (move left)
  72.         neg     ax              ;Width = abs(DeltaX)
  73. SetAdvanceAmt:
  74.     mov    [bp+AdvanceAmt],dx
  75. ; Figure out whether the edge is diagonal, X-major (more horizontal),
  76. ; or Y-major (more vertical) and handle appropriately.
  77.     cmp    ax,bx        ;if Width==Height, it's a diagonal edge
  78.     jz    IsDiagonal    ;it's a diagonal edge--special case
  79.     jb    YMajor        ;it's a Y-major (more vertical) edge
  80.                 ;it's an X-major (more horz) edge
  81.         sub     dx,dx           ;prepare DX:AX (Width) for division
  82.         div     bx        ;Width/Height
  83.                 ;DX = error term advance per scan line
  84.     mov    si,ax        ;SI = minimum # of pixels to advance X
  85.                 ; on each scan line
  86.         test    [bp+AdvanceAmt],8000h ;move left or right?
  87.         jz      XMajorAdvanceAmtSet ;right, already set
  88.         neg     si              ;left, negate the distance to advance
  89.                 ; on each scan line
  90. XMajorAdvanceAmtSet:            ;
  91.     mov    ax,[bp+X1]    ;starting X coordinate
  92.         cmp     [bp+SkipFirst],1 ;skip the first point?
  93.         jz    XMajorSkipEntry    ;yes
  94. XMajorLoop:
  95.     mov    [di],ax        ;store the current X value
  96.     add    di,size HLine    ;point to the next HLine struc
  97. XMajorSkipEntry:
  98.     add    ax,si        ;set X for the next scan line
  99.     add    cx,dx        ;advance error term
  100.     jle    XMajorNoAdvance ;not time for X coord to advance one
  101.                 ; extra
  102.     add    ax,[bp+AdvanceAmt] ;advance X coord one extra
  103.         sub     cx,[bp+Height]  ;adjust error term back
  104. XMajorNoAdvance:
  105.         dec     bx        ;count off this scan line
  106.         jnz     XMajorLoop
  107.     jmp    ScanEdgeDone
  108.     align    2
  109. ToScanEdgeExit:
  110.     jmp    ScanEdgeExit
  111.         align    2
  112. IsVertical:
  113.     mov    ax,[bp+X1]    ;starting (and only) X coordinate
  114.     sub    bx,[bp+SkipFirst] ;loop count = Height - SkipFirst
  115.         jz      ScanEdgeExit     ;no scan lines left after skipping 1st
  116. VerticalLoop:
  117.     mov    [di],ax        ;store the current X value
  118.     add    di,size HLine    ;point to the next HLine struc
  119.     dec    bx        ;count off this scan line
  120.     jnz    VerticalLoop
  121.     jmp    ScanEdgeDone
  122.         align    2
  123. IsDiagonal:
  124.     mov    ax,[bp+X1]    ;starting X coordinate
  125.         cmp     [bp+SkipFirst],1 ;skip the first point?
  126.     jz    DiagonalSkipEntry ;yes
  127. DiagonalLoop:    
  128.     mov    [di],ax        ;store the current X value
  129.     add    di,size HLine    ;point to the next HLine struc
  130. DiagonalSkipEntry:
  131.     add    ax,dx        ;advance the X coordinate
  132.     dec    bx        ;count off this scan line
  133.     jnz    DiagonalLoop
  134.     jmp    ScanEdgeDone
  135.         align    2
  136. YMajor:
  137.     push    bp        ;preserve stack frame pointer
  138.     mov    si,[bp+X1]    ;starting X coordinate
  139.         cmp     [bp+SkipFirst],1 ;skip the first point?
  140.     mov    bp,bx        ;put Height in BP for error term calcs
  141.         jz    YMajorSkipEntry    ;yes, skip the first point
  142. YMajorLoop:
  143.     mov    [di],si        ;store the current X value
  144.     add    di,size HLine    ;point to the next HLine struc
  145. YMajorSkipEntry:
  146.     add    cx,ax        ;advance the error term
  147.     jle    YMajorNoAdvance ;not time for X coord to advance
  148.     add    si,dx        ;advance the X coordinate
  149.         sub     cx,bp        ;adjust error term back
  150. YMajorNoAdvance:
  151.         dec     bx        ;count off this scan line
  152.         jnz     YMajorLoop
  153.     pop    bp        ;restore stack frame pointer
  154. ScanEdgeDone:
  155.     cmp    [bp+SetXStart],1 ;were we working with XStart field?
  156.     jz    UpdateHLinePtr    ;yes, DI points to the next XStart
  157.     sub    di,XEnd        ;no, point back to the XStart field
  158. UpdateHLinePtr:
  159.     mov    bx,[bp+EdgePointPtr] ;point to pointer to HLine array
  160.     mov    [bx],di        ;update caller's HLine array pointer
  161. ScanEdgeExit:
  162.     pop    di        ;restore caller's register variables
  163.     pop    si
  164.         mov     sp,bp           ;deallocate local variables
  165.     pop    bp        ;restore caller's stack frame
  166.     ret
  167. _ScanEdge    endp
  168.     end
  169.